/**
 * 发票OCR查验
 */
import React from "react";
import config from "config";
import { connect } from "react-redux";
import { messages, queryCurrencyPrecision } from "share/common";
import { Upload, Modal, message, Button, Row, Col } from "antd";

import errorMessage from "share/errorMessage";
import loadingImg from "images/expense-report/loading.png";
import uploadingImg from "images/expense-report/image-uploading.png";
import defaultImg from "images/expense-report/default-image.png";

import baseService from "share/base.service";
import expenseService from "containers/my-account/expense.service";
import "styles/my-account/components/invoice-ocr-check.scss";
import dataSources from "../data-sources/data-sources";
const { ocrTypeMap } = dataSources;

class InvoiceOCRCheck extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      fileList: [],
      successFileList: [],
      errorFileNum: 0,
      uploadModalVisible: false,
      invoiceModalVisible: false,
      invoiceList: [],
      selectedReceiptIndex: null,
    };
    this.bigThan10FileNum = 0; //超过10M的图片数量
    this.notRightTypeNum = 0; //不是正确文件类型的附件数量
    this.totalUploadNum = 0; //总上传图片的总数（不包括超过10M的图片）
  }

  componentWillReceiveProps() {
    this.setState({
      fileList: [],
      successFileList: [],
      errorFileNum: 0,
    });
  }

  beforeUpload = (file, type) => {
    if (window.ISIE9) {
      //如果是IE9则不校验
      return true;
    }
    let isLt10M = file.size / 1024 / 1024 <= 10;
    let isRightType =
      (type === "image" && /image\//.test(file.type)) ||
      (type === "pdf" && /\/pdf/.test(file.type)) ||
      (type === "ofd" && file.name.match(/.ofd$/));

    if (!isLt10M) {
      //大于10M的附件
      this.bigThan10FileNum++;
    } else if (!isRightType) {
      //非正确文件类型的附件
      this.notRightTypeNum++;
    } else {
      this.totalUploadNum++;
    }
    if (this.totalUploadNum === 10) {
      message.warning(messages("my-account.key315") /*单次最多上传9个文件*/);
    }
    return isLt10M && isRightType && this.totalUploadNum <= 9;
  };

  //图片上传
  handleImageUpload = (res) => {
    if (window.ISIE9) {
      //IE9不支持多选
      this.setState(
        { uploadModalVisible: true, fileList: [res], successFileList: [res] },
        this.handleCheckOCR
      );
      return;
    }
    const { file, fileList } = res;
    //token失效
    if (file.response && file.response.error === "invalid_token") {
      this.handleCancelImport();
      //token失效后，重新请求下language接口，可以refreshToken
      baseService.getLanguageList();
      message.error(messages("my-account.key272") /*token失效请重试*/);
      return;
    }
    let { successFileList, errorFileNum } = this.state;
    //fileList返回了所有文件"[Object File]"及可以正常上传的文件"[object Object]"
    //fileNum为可以正常上传的文件数量（请求上传接口的次数）
    let fileNum = 0;
    fileList &&
      fileList.map((item) => {
        String(item) === "[object Object]" && fileNum++;
      });
    this.setState({ uploadModalVisible: true });
    let status = file.status;
    if (status === "done") {
      successFileList.push(file.response);
    }
    if (status === "error") {
      errorFileNum++;
    }
    this.setState({ fileList, successFileList, errorFileNum }, () => {
      if (this.totalUploadNum === 0) {
        if (this.bigThan10FileNum > 0) {
          message.error(messages("my-account.key316") /*文件大小不能超过10MB*/);
        }
        if (this.notRightTypeNum > 0) {
          message.error(messages("my-account.key287") /*文件格式错误*/);
        }
        this.handleCancelImport();
      } else if (errorFileNum > 0 && fileNum === errorFileNum) {
        message.error(
          errorFileNum === 1
            ? (file.response && file.response.message) ||
                messages("my-account.key317") /*文件上传失败*/
            : messages("my-account.key317") /*文件上传失败*/
        );
        this.handleCancelImport();
      } else if (fileNum === successFileList.length + errorFileNum) {
        this.handleCheckOCR();
      }
    });
  };

  //发票OCR识别
  handleCheckOCR = () => {
    const { successFileList } = this.state;
    let params = [];
    successFileList.map((item) => {
      params.push({
        attachmentOID: item.attachmentOID,
        fileURL: item.fileURL,
        fileName: item.fileName,
        fileType: item.fileType,
      });
    });
    const serviceName = this.props.type === "ofd" ? "checkOFD" : "checkOCR";

    params.length &&
      expenseService[serviceName](params)
        .then((res) => {
          if (res.data.success) {
            let list = res.data.rows.receiptList;
            list.map((item) => {
              if (item.invoiceGoods && item.invoiceGoods.length > 0) {
                item.invoiceGoods.map((a) => {
                  a.taxPrice = a.taxPrice ? a.taxPrice : 0;
                  a.taxRateString = a.taxRateString ? a.taxRateString : 0;
                });
              }
              item.tax = item.tax ? item.tax : 0;
              item.taxString = item.taxString ? item.taxString : "0";
            });
            // ocr 识别不到的发票类型，需去手动录入，选择小票
            if (list && list.length > 0) {
              let isHasInvioceNo = false;
              list.map((item) => {
                if (!item.invoiceTypeNo) {
                  isHasInvioceNo = true;
                }
              });
              if (isHasInvioceNo) {
                this.handleCancelImport();
                message.warning("未识别该种发票类型，请手工录入该发票");
              } else {
                this.handleCheckInvoice(res.data.rows ? list || [] : []);
              }
            } else {
              this.handleCheckInvoice(res.data.rows ? list || [] : []);
            }
          } else {
            this.handleCancelImport();
            message.error(
              messages("my-account.key318") /*文件识别失败，请重试*/
            );
          }
        })
        .catch((e) => {
          this.handleCancelImport();
          errorMessage(e.response);
        });
  };

  //信息是否完整（不需要补录）
  isCompleteInvoice = (resultCode) => {
    // 不完整code
    const resultCodes = ["R_2002", "R_2007", "R_2008", "R_2009"];
    return !resultCodes.includes(resultCode);
  };

  //发票是否查验成功
  isCheckSuccessfulInvoice = (invoiceInfo) => {
    return invoiceInfo.checkResult === "R_0000";
  };

  /**
   * 判断发票是否可编辑
   * 可编辑场景
   *       1: resultCode为130102（特殊校验码）
   *       2: 不可生成费用且为缺少字段（需要补录信息）
   *       3: ocr 不可生成费用且查验失败
   *       4: 查验失败
   */
  isEditableInvoice = (invoice, isOcr) => {
    if (invoice.resultCode === "130102") {
      return true;
    }
    if (invoice.isOk === "N") {
      //不可生成费用
      // ocr 查验失败可编辑
      if (!this.isCheckSuccessfulInvoice(invoice.invoiceInfo) && isOcr) {
        return true;
      }
      // 信息不全
      return !this.isCompleteInvoice(invoice.resultCode);
    }
    // 或者查验失败即可编辑
    return !this.isCheckSuccessfulInvoice(invoice.invoiceInfo);
  };

  //发票查验
  handleCheckInvoice = (receiptList) => {
    const { expenseType } = this.props;
    let params = receiptList.map((item) => {
      return {
        invoiceInfo: {
          ...item,
          expenseTypeId: this.props.expenseType.id,
          entityTypeCode: this.props.expenseType.code,
        },
      };
    });
    expenseService
      .checkInvoiceBatch(params)
      .then((res) => {
        //对于支持单发票的费用，只有可编辑的发票或者可生成费用的发票需显示
        let invoiceList = res.data.filter((item) => item);
        let msg = null;
        invoiceList.map((item) => {
          item.resultCode === "R_2010" && (msg = item.msg);
          item.invoiceInfo.editable = this.isEditableInvoice(item, true);
        });
        msg && message.success(msg);
        this.setState({ invoiceList }, () => {
          if (expenseType.multipleInvoiceSupported) {
            //多发票
            this.handleCancelImport();
            this.props.checkSuccess(invoiceList);
          } else {
            if (invoiceList.length === 0) {
              this.handleCancelImport();
              message.error(messages("my-account.key257") /*无可添加发票*/);
            } else if (invoiceList.length === 1) {
              this.setState(
                { uploadModalVisible: false, selectedReceiptIndex: 0 },
                this.onOk
              );
            } else {
              this.setState({
                uploadModalVisible: false,
                invoiceModalVisible: true,
              });
            }
          }
        });
      })
      .catch((e) => {
        console.error(e);
        this.handleCancelImport();
        errorMessage(e.response);
      });
  };

  /*获取币种精度*/
  getCurrencyPrecision = (invoice) => {
    if (invoice && invoice.vatInvoiceCurrencyCode) {
      return queryCurrencyPrecision(invoice.vatInvoiceCurrencyCode);
    }
    return queryCurrencyPrecision();
  };

  //财务保存发票
  saveReceiptByFinance = (receipt) => {
    let { nowExpense } = this.props;
    receipt.invoiceOID = nowExpense.invoiceOID;
    this.setState({ loading: true });
    expenseService
      .financialAuditInvoice(receipt)
      .then((res) => {
        if (res.data.code === "0000") {
          this.setState({
            loading: false,
            uploadModalVisible: false,
            invoiceModalVisible: false,
          });
          message.success(messages("my-account.key258") /*发票添加成功*/);
          this.props.importSuccessInvoice(res.data.rows);
        } else {
          let errorList = res.data.rows ? res.data.rows.errorList || [] : [];
          let warningInfo = [];
          errorList.map((item) => {
            warningInfo.push(
              `${item.title}${item.title ? ":" : ""}${item.message}`
            );
          });
          message.error(warningInfo.join("/"));
          this.setState({ loading: false, uploadModalVisible: false });
        }
      })
      .catch((e) => {
        this.setState({ loading: false, uploadModalVisible: false });
        errorMessage(e.response);
      });
  };

  onOk = () => {
    const { createType } = this.props;
    let { invoiceList, selectedReceiptIndex } = this.state;
    let selectedInvoice = invoiceList[selectedReceiptIndex];
    let invoiceInfo = selectedInvoice.invoiceInfo;
    let errorList = selectedInvoice.errorList || [];
    errorList.map((errorItem, errorIndex) => {
      errorList[errorIndex].name = errorItem.title;
      errorList[errorIndex].toast = errorItem.message;
    });
    invoiceInfo.receiptLabels = errorList;
    //发票不可编辑
    if (!this.isEditableInvoice(selectedInvoice, true)) {
      //发票不可生成费用，进入发票不可编辑页
      if (selectedInvoice.isOk === "N") {
        this.props.toEditDisabledPage(invoiceInfo);
      } else {
        //发票直接导入到费用详情页
        if (createType === 2) {
          //财务添加发票
          this.saveReceiptByFinance(invoiceInfo);
        } else {
          this.setState({ invoiceModalVisible: false });
          this.props.importSuccessInvoice(invoiceInfo);
          message.success(messages("my-account.key258") /*发票添加成功*/);
        }
      }
    } else {
      this.setState({ invoiceModalVisible: false });
      invoiceInfo.resultCode = selectedInvoice.resultCode;
      this.props.invoiceEdit(invoiceInfo);
    }
    this.handleCancelImport();
    this.setState({ selectedReceiptIndex: null });
  };

  //取消导入
  handleCancelImport = () => {
    this.bigThan10FileNum = 0;
    this.notRightTypeNum = 0;
    this.totalUploadNum = 0;
    this.setState({
      uploadModalVisible: false,
      invoiceModalVisible: false,
      invoiceList: [],
      fileList: [],
      successFileList: [],
      errorFileNum: 0,
      selectedReceiptIndex: null,
    });
  };

  render() {
    const { authToken, type } = this.props;
    const {
      loading,
      uploadModalVisible,
      invoiceModalVisible,
      fileList,
      invoiceList,
      selectedReceiptIndex,
    } = this.state;
    return (
      <div className="invoice-ocr-check">
        <Upload
          name="file"
          data={() => {
            return { attachmentType: ocrTypeMap[type].attachmentType };
          }}
          action={`${config.baseUrl}/api/upload/attachment`}
          headers={{ Authorization: "Bearer " + authToken.access_token }}
          accept={ocrTypeMap[type].accept}
          listType="text"
          multiple
          fileList={fileList}
          showUploadList={false}
          beforeUpload={(file) => this.beforeUpload(file, type)}
          onChange={this.handleImageUpload}
        >
          <div className="ocr-upload-button">{ocrTypeMap[type].text}</div>
        </Upload>

        <Modal
          visible={uploadModalVisible}
          maskClosable={false}
          footer={null}
          closable={false}
          width={330}
          wrapClassName="invoice-ocr-checking"
        >
          <img src={loadingImg} className="checking-img" />
          <img src={uploadingImg} className="checking-img-content" />
          <div className="checking-title">
            {messages("my-account.key321") /*正在识别文件*/}...
          </div>
        </Modal>

        <Modal
          visible={invoiceModalVisible}
          maskClosable={false}
          width={668}
          title={
            <div>
              {" "}
              {messages("my-account.key261") /*请选择一张发票*/}
              <span className="little-tip">
                （
                {messages("my-account.key262") /*该费用类型只支持关联一张发票*/}
                ）
              </span>
            </div>
          }
          wrapClassName="invoice-ocr-checked-list"
          onCancel={this.handleCancelImport}
          footer={[
            <Button onClick={this.handleCancelImport}>
              {messages("common.cancel") /*取消*/}
            </Button>,
            <Button
              type="primary"
              disabled={selectedReceiptIndex === null}
              loading={loading}
              onClick={this.onOk}
            >
              {messages("common.ok") /*确定*/}
            </Button>,
          ]}
        >
          <Row className="invoice-container">
            {invoiceList.map((item, index) => (
              <Col
                className={`invoice-block ${
                  index % 3 !== 0 ? "invoice-block-left" : ""
                } ${selectedReceiptIndex === index ? "invoice-selected" : ""}`}
                onClick={() =>
                  this.setState({
                    selectedReceiptIndex:
                      selectedReceiptIndex === index ? null : index,
                  })
                }
              >
                <img
                  src={
                    item.invoiceInfo && item.invoiceInfo.slicingAttachment
                      ? item.invoiceInfo.slicingAttachment.fileURL
                      : defaultImg
                  }
                  className="invoice-image"
                />
                <div className="invoice-amount">
                  {item.invoiceInfo.vatInvoiceCurrencyCode}{" "}
                  {item.invoiceInfo.fee
                    ? (item.invoiceInfo.fee / 100).toFixed(
                        this.getCurrencyPrecision(item.invoiceInfo)
                      )
                    : "-"}
                </div>
              </Col>
            ))}
          </Row>
        </Modal>
      </div>
    );
  }
}

InvoiceOCRCheck.propTypes = {
  type: React.PropTypes.string, //image pdf
  expenseType: React.PropTypes.object,
  nowExpense: React.PropTypes.object,
  createType: React.PropTypes.number, //1.用户操作类型 2.财务操作类型
  checkSuccess: React.PropTypes.func,
  invoiceEdit: React.PropTypes.func, //编辑发票
  importSuccessInvoice: React.PropTypes.func, //导入查验成功的发票
  toEditDisabledPage: React.PropTypes.func, //查验成功但不可生成费用的发票到发票不可编辑页
};

function mapStateToProps(state) {
  return {
    authToken: state.main.authToken,
  };
}

export default connect(mapStateToProps)(InvoiceOCRCheck);
